
#pragma once

#include "ly/types.hpp"
#include "ly/vec2.hpp"

namespace ly {

/**
 * @brief 重复类型
 */
enum ArrayType {
  None = 0,     ///< 不重复
  Rectangular,  ///< 重复为[columns × rows]矩阵，间隔为spacing，p(i,j) = (i * spacing.x, j * spacing.y)
  Regular,      ///< 重复为[columns × rows]矩阵，沿着v1到v2   ，p(i,j) = v1 * i + v2 * j
  Explicit,     ///< 按照原点和offsets重复，p(0) = {0, 0}，p(k+1) = offsets(k)
  ExplicitX,    ///< 按照原点和coords重复，p(0) = {0, 0}，p(k+1) = (coords(k),0)
  ExplicitY,    ///< 按照原点和coords重复，p(0) = {0, 0}，p(k+1) = (0,coords(k))
};

template <class C>
class rectangular_array {
 public:
  typedef C coord_t;
  typedef ly::point<C> point_t;
  rectangular_array() {};
  rectangular_array(coord_t columns, coord_t rows, const point_t& spacing) : m_columns(columns), m_rows(rows), m_spacing(spacing) {};

  void spacing(const point_t& s) { m_spacing = s; }
  void columns(coord_t v) { m_columns = v; }
  void rows(coord_t v) { m_rows = v; }

 private:
  coord_t m_columns{0}, m_rows{0};  //< 沿着x轴行数, 沿着y轴列数
  point_t m_spacing{0, 0};          //< 间隔
};

template <class C>
class regular_array {
 public:
  typedef C coord_t;
  typedef ly::point<C> point_t;

 private:
  coord_t m_columns{0}, m_rows{0};  //< 沿着x轴行数, 沿着y轴列数
  point_t m_v1, m_v2;               ///< Regular 轴1, 周2
};

template <class C>
class explicitx_array {
  typedef C coord_t;

 private:
  std::vector<coord_t> m_coords;  ///< ExplicitX 或 ExplicitY 使用，不应包含原点，因为默认包含
};

template <class C>
class explicity_array {
 public:
  typedef C coord_t;

 private:
  std::vector<coord_t> m_coords;  ///< ExplicitX 或 ExplicitY 使用，不应包含原点，因为默认包含
};

template <class C>
class explicit_array {
 public:
  typedef std::vector<ly::point<C>> points_t;

 private:
  points_t m_offsets;  ///< Explicit 使用，不应包含原点，因为默认包含
};

template <class C>
class array {
 public:
  typedef C coord_t;
  typedef ly::point<C> point_t;
  typedef std::vector<ly::point<C>> points_t;

  ArrayType type;  ///< 重复类型

  coord_t columns{0};  ///< 沿着x轴行数
  coord_t rows{0};     ///< 沿着y轴列数
  point_t spacing;     ///< Rectangular 间隔
  point_t v1;          ///< Regular 轴1
  point_t v2;          ///< Regular 轴2

  points_t offsets;           ///< Explicit 使用，不应包含原点，因为默认包含
  std::vector<Coord> coords;  ///< ExplicitX 或 ExplicitY 使用，不应包含原点，因为默认包含
};

typedef array<Coord> Array;
typedef array<DCoord> DArray;

typedef regular_array<Coord> RegularArray;
typedef regular_array<DCoord> DRegularArray;

typedef rectangular_array<Coord> RectangularArray;
typedef rectangular_array<DCoord> DRectangularArray;

typedef explicit_array<Coord> ExplicitArray;
typedef explicit_array<DCoord> DExplicitArray;

typedef explicitx_array<Coord> ExplicitXArray;
typedef explicitx_array<DCoord> DExplicitXArray;

typedef explicity_array<Coord> ExplicitYArray;
typedef explicity_array<DCoord> DExplicitYArray;

}  // namespace ly
